home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.1 / Examples1 / locale / SelfLoad / catalog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-12  |  11.7 KB  |  406 lines

  1. /* catalog.c - for using a catalog under V37 without locale.library
  2.  * Also requires getcatalogstr.asm
  3.  *
  4.  * Requires these externals from the application it is linked with:
  5.  *
  6.  *  extern struct Library *LocaleBase  (NULL under <V38)
  7.  *  extern struct Library *UtilityBase (required)
  8.  *  for XGetString function:
  9.  *  extern struct Catalog *catalog
  10.  *  extern struct CatCompArrayType *StringArray;
  11.  *  extern ULONG  StringCount;
  12.  *
  13.  */
  14.  
  15. /* includes */
  16. #include <exec/types.h>
  17. #include <exec/memory.h>
  18. #include <exec/lists.h>
  19. #include <exec/libraries.h>
  20. #include <dos/dos.h>
  21. #include <dos/dosextens.h>
  22. #include <libraries/iffparse.h>
  23. #include <string.h>
  24.  
  25. /* prototypes */
  26. #include <clib/exec_protos.h>
  27. #include <clib/dos_protos.h>
  28. #include <clib/iffparse_protos.h>
  29. #include <clib/locale_protos.h>
  30. #include <clib/utility_protos.h>
  31.  
  32. /* direct ROM interface */
  33. extern struct Library *SysBase;
  34. extern struct Library *DOSBase;
  35. #include <pragmas/exec_pragmas.h>
  36. #include <pragmas/dos_pragmas.h>
  37. #include <pragmas/iffparse_pragmas.h>
  38. #include <pragmas/locale_pragmas.h>
  39. #include <pragmas/utility_pragmas.h>
  40.  
  41. /* application includes */
  42. #include "catalog.h"
  43.  
  44. /* defined in application */
  45. extern struct Library *LocaleBase;
  46. extern struct Library *UtilityBase;
  47. extern struct Catalog *catalog;
  48. extern struct CatCompArrayType *StringArray;
  49. extern ULONG  StringCount;
  50.  
  51. /*****************************************************************************/
  52.  
  53.  
  54. #define ID_CTLG MAKE_ID('C','T','L','G')
  55. #define ID_STRS MAKE_ID('S','T','R','S')
  56. #define ID_CSET MAKE_ID('C','S','E','T')
  57. #define ID_LANG MAKE_ID('L','A','N','G')
  58. #define ID_FVER MAKE_ID('F','V','E','R')
  59.  
  60. #define IFFPrefChunkCnt 4
  61. static LONG far IFFPrefChunks[] =
  62. {
  63.     ID_CTLG, ID_STRS,
  64.     ID_CTLG, ID_CSET,
  65.     ID_CTLG, ID_FVER,
  66.     ID_CTLG, ID_LANG
  67. };
  68.  
  69.  
  70. /*****************************************************************************/
  71.  
  72.  
  73. struct CodeSet
  74. {
  75.     ULONG cs_CodeSet;
  76.     ULONG cs_Reserved[7];
  77. };
  78.  
  79.  
  80. /*****************************************************************************/
  81.  
  82.  
  83.  
  84. /*****************************************************************************/
  85.  
  86.  
  87. static BOOL LoadCatalog(struct XCatalog *catalog, STRPTR name,
  88.                         STRPTR language, ULONG reqVersion)
  89. {
  90. struct IFFHandle   *iff;
  91. struct ContextNode *cn;
  92. BOOL             dataFlag = FALSE;
  93. BOOL            result = FALSE;
  94. LONG                error;
  95. struct Library     *IFFParseBase;
  96. LONG            bufSize;
  97. ULONG           *ptr,*lastpoke;
  98. ULONG            len;
  99. struct CodeSet      codeset;
  100. char            buffer[100];
  101. ULONG            version,revision;
  102. LONG            chars;
  103. UWORD            i;
  104.  
  105.     if (!(IFFParseBase = OpenLibrary("iffparse.library",0)))
  106.     {
  107.         SetIoErr(ERROR_INVALID_RESIDENT_LIBRARY);
  108.         return(FALSE);
  109.     }
  110.  
  111.     if (iff = AllocIFF())
  112.     {
  113.         if (iff->iff_Stream = (ULONG)Open(name,MODE_OLDFILE))
  114.         {
  115.             InitIFFasDOS(iff);
  116.  
  117.             if (!OpenIFF(iff,IFFF_READ))
  118.             {
  119.                 if (!ParseIFF(iff,IFFPARSE_STEP))
  120.                 {
  121.                     cn = CurrentChunk(iff);
  122.                     if (cn->cn_ID == ID_FORM && cn->cn_Type == ID_CTLG)
  123.                     {
  124.                         if (!StopChunks(iff,IFFPrefChunks,IFFPrefChunkCnt))
  125.                         {
  126.                             while (TRUE)
  127.                             {
  128.                                 if (error = ParseIFF(iff,IFFPARSE_SCAN))
  129.                                 {
  130.                                     if (error == IFFERR_EOF)
  131.                                         result = dataFlag;
  132.  
  133.                                     break;
  134.                                 }
  135.  
  136.                                 cn = CurrentChunk(iff);
  137.  
  138.                                 if (cn->cn_ID == ID_STRS && cn->cn_Type == ID_CTLG)
  139.                                 {
  140.                                     if (bufSize = cn->cn_Size)
  141.                                     {
  142.                                         if (!(catalog->ec_Strings = AllocVec(bufSize,MEMF_PUBLIC)))
  143.                                             break;
  144.  
  145.                                         if (ReadChunkBytes(iff,catalog->ec_Strings,bufSize) != bufSize)
  146.                                             break;
  147.                                     }
  148.                                     dataFlag = TRUE;
  149.                                 }
  150.                                 else if (cn->cn_ID == ID_LANG && cn->cn_Type == ID_CTLG)
  151.                                 {
  152.                                     if (cn->cn_Size > 32)
  153.                                         break;
  154.  
  155.                                     if (ReadChunkBytes(iff,catalog->ec_LanguageStr,cn->cn_Size) != cn->cn_Size)
  156.                                         break;
  157.  
  158.                                     if (strcmp(language,catalog->ec_LanguageStr) != 0)
  159.                                         break;
  160.                                 }
  161.                                 else if (cn->cn_ID == ID_FVER && cn->cn_Type == ID_CTLG)
  162.                                 {
  163.                                     if (cn->cn_Size > 100)
  164.                                         break;
  165.  
  166.                                     if (ReadChunkBytes(iff,buffer,cn->cn_Size) != cn->cn_Size)
  167.                                         break;
  168.  
  169.                                     buffer[99] = 0;
  170.                                     i = 0;
  171.                                     while (buffer[i] && (buffer[i] != ' '))
  172.                                         i++;
  173.                                     while (buffer[i] && (buffer[i] == ' '))
  174.                                         i++;
  175.                                     while (buffer[i] && (buffer[i] != ' '))
  176.                                         i++;
  177.  
  178.                                     if (buffer[i])
  179.                                     {
  180.                                         if ((chars = StrToLong(&buffer[i],(LONG *)&version)) < 0)
  181.                                             break;
  182.  
  183.                                         i += chars;
  184.                                         if (buffer[i++])
  185.                                         {
  186.                                             if (StrToLong(&buffer[i],(LONG *)&revision) < 0)
  187.                                                 break;
  188.                                         }
  189.  
  190.                                         catalog->ec_Version  = version;
  191.                                         catalog->ec_Revision = revision;
  192.  
  193.                                         if (reqVersion && (version != reqVersion))
  194.                                             break;
  195.                                     }
  196.                                 }
  197.                                 else if (cn->cn_ID == ID_CSET && cn->cn_Type == ID_CTLG)
  198.                                 {
  199.                                     if (ReadChunkBytes(iff,&codeset,sizeof(struct CodeSet)) != sizeof(struct CodeSet))
  200.                                         break;
  201.  
  202.                                     catalog->ec_CodeSet = codeset.cs_CodeSet;
  203.                                 }
  204.                             }
  205.                         }
  206.                     }
  207.                 }
  208.                 CloseIFF(iff);
  209.             }
  210.             Close(iff->iff_Stream);
  211.         }
  212.         FreeIFF(iff);
  213.     }
  214.     else
  215.     {
  216.         SetIoErr(ERROR_NO_FREE_STORE);
  217.     }
  218.  
  219.     CloseLibrary(IFFParseBase);
  220.  
  221.     if (result)
  222.     {
  223.         catalog->ec_Language = catalog->ec_LanguageStr;
  224.  
  225.         /* now zip through buffer, changing the length longs to be pointers
  226.          * to the next string instead. This speeds up the string searching
  227.          * code as it doesn't need to add and compensate for padding as we do
  228.          * that here.
  229.          */
  230.  
  231.         if (ptr = catalog->ec_Strings)
  232.         {
  233.             lastpoke = NULL;
  234.             while (bufSize)
  235.             {
  236.                 ptr++;                      // skip id longword
  237.                 len = *ptr;                 // get length
  238.                 len = ((len+3) / 4) * 4;    // round up to multiple of 4
  239.                 *ptr = (ULONG)ptr+len+4;    // change length to point to next string
  240.                 lastpoke = ptr;
  241.                 ptr = (ULONG *)*ptr;
  242.                 bufSize -= len+8;
  243.             }
  244.  
  245.             if (lastpoke)
  246.                 *lastpoke = NULL;
  247.         }
  248.     }
  249.     else
  250.     {
  251.         FreeVec(catalog->ec_Strings);
  252.         catalog->ec_Strings = NULL;
  253.     }
  254.  
  255.     return(result);
  256. }
  257.  
  258.  
  259. /*****************************************************************************/
  260.  
  261.  
  262. /* tags on stack interface XOpenCatalog */
  263.  
  264. struct Catalog *XOpenCatalog(struct Locale *locale, STRPTR name, ULONG tags, ...)
  265.     {
  266.     return(XOpenCatalogA(locale, name, (struct TagItem *)&tags));
  267.     }
  268.  
  269. /* pointer to tag list interface XOpenCatalogA */
  270. struct Catalog *XOpenCatalogA(struct Locale *locale,
  271.                  STRPTR name,
  272.                  struct TagItem *tags)
  273. {
  274. struct XCatalog *result = NULL;
  275. struct Process    *process;
  276. char           path[100];
  277. STRPTR             lang;
  278. STRPTR             builtInLanguage;
  279. UWORD           version;
  280. BPTR               lock;
  281. BOOL               doProgDir;
  282. UBYTE              cnt;
  283. APTR               oldWP;
  284.  
  285.     if(DOSBase->lib_Version < 36)    return(NULL);
  286.  
  287.     if(LocaleBase)    return(OpenCatalogA(locale,name,tags));
  288.  
  289.     builtInLanguage = (STRPTR)GetTagData(OC_BuiltInLanguage,(ULONG)"english",tags);
  290.     version         = (UWORD) GetTagData(OC_Version,0,tags);
  291.     lang            = (STRPTR)GetTagData(OC_Language,0,tags);
  292.  
  293.  
  294.     /* No LocaleBase, no user prefs. Can't load without explicit Language tag */
  295.     if (!lang)        return(NULL);
  296.  
  297.     /* Preferred language matches built-in language */
  298.     if (builtInLanguage && (strcmp(lang,builtInLanguage) == 0)) return(NULL);
  299.  
  300.     /* Try explicit load */
  301.  
  302.     if (!(result = AllocVec(sizeof(struct XCatalog)+strlen(name)+1,MEMF_PUBLIC|MEMF_CLEAR)))
  303.                 return(NULL);
  304.  
  305.     result->ec_Link.ln_Name = (STRPTR)((ULONG)result+sizeof(struct XCatalog));
  306.     strcpy(result->ec_Link.ln_Name,name);
  307.  
  308.     process = (struct Process *)FindTask(NULL);
  309.     oldWP = process->pr_WindowPtr;
  310.     process->pr_WindowPtr = (APTR)-1;
  311.  
  312.     /* To match the documented search path for catalogs */
  313.     doProgDir = TRUE;
  314.     if (!(lock = Lock("PROGDIR:",ACCESS_READ)))
  315.           if (lock = Lock("LOCALE:",ACCESS_READ))
  316.                 doProgDir = FALSE;
  317.     if(lock) UnLock(lock);
  318.  
  319.     process->pr_WindowPtr = oldWP;
  320.  
  321.     cnt = 3;
  322.     while (--cnt)
  323.         {
  324.         if (doProgDir)
  325.              {
  326.              doProgDir = FALSE;
  327.              strcpy(path,"PROGDIR:Catalogs");
  328.              AddPart(path,lang,sizeof(path));
  329.              AddPart(path,name,sizeof(path));
  330.              if (GetProgramDir() && LoadCatalog(result,path,lang,version))
  331.                             break;
  332.              }
  333.         else
  334.              {
  335.              doProgDir = TRUE;
  336.              strcpy(path,"LOCALE:Catalogs");
  337.              AddPart(path,lang,sizeof(path));
  338.              AddPart(path,name,sizeof(path));
  339.              if (LoadCatalog(result,path,lang,version))
  340.                        break;
  341.              }
  342.          }
  343.  
  344.     if(!cnt)
  345.     {
  346.         FreeVec(result);
  347.         result = NULL;
  348.         }
  349.  
  350.     return((struct Catalog *)result);
  351. }
  352.  
  353.  
  354. /*****************************************************************************/
  355.  
  356. VOID XCloseCatalog(struct Catalog *catalog)
  357. {
  358.     if (catalog)
  359.     {
  360.     if(LocaleBase)    CloseCatalog(catalog);
  361.     else
  362.     {
  363.         FreeVec(((struct XCatalog *)catalog)->ec_Strings); /* can accept NULL */
  364.         FreeVec(catalog);
  365.     }
  366.     }
  367. }
  368.  
  369. struct CatCompArrayType
  370. {
  371.     LONG   cca_ID;
  372.     STRPTR cca_Str;
  373. };
  374.  
  375. static UBYTE *NULLSTRING = "";
  376.  
  377. /* references external StringArray (pointer to CatCompArray)
  378.  *                     StringCount
  379.  *                     catalog
  380.  */
  381. STRPTR XGetString(LONG id)
  382.     {
  383.     struct CatCompArrayType *cca;
  384.     UBYTE *s = NULLSTRING;
  385.     ULONG k;
  386.  
  387.     cca = StringArray;
  388.  
  389.     for(k=0; k<StringCount; k++, cca++)
  390.     {
  391.     if(cca->cca_ID == id)
  392.         {
  393.         s = cca->cca_Str;
  394.         break;
  395.         }
  396.     }
  397.  
  398.     if((catalog)&&(*s))
  399.     {
  400.     s = XGetCatalogStr(catalog,id,s);
  401.     }
  402.  
  403.     return(s);
  404.     }
  405.  
  406.